//#############################################################################
//#############################################################################
//This source file was written by Mert Dogar. If you have some questions about
//the source code, please do not hesitate to ask me.
//The code is under GPL.
//Email: mertdogar@gmail.com , http://code.google.com/p/electron-cds
//#############################################################################
//#############################################################################

//#############################################
//Glade Include Files
#include <libglademm/xml.h>
#include <gtkmm.h>
#include <iostream>
#include <glade/glade.h>

#ifdef ENABLE_NLS
#  include <libintl.h>
#endif
//#############################################

//#############################################
//General Purpose Functions & Definitions

#include "main.h"

#include "project.h"

void show_property_window(Glib::RefPtr<Gnome::Glade::Xml> refXml, project &prj);


project prj;

logs applog; //log class. filename is defined in the init_main_window () function



Glib::RefPtr<Gnome::Glade::Xml> refXml; //Gui File RefPtr
Cairo::RefPtr<Cairo::Context> myContext; //CAiro Context
//#############################################

//GUI Definition
#define GLADE_FILE "gui.glade"

Gtk::Window* main_win = 0;


//Extra Definitions
string part;

vector2 pos; //Mouse pointer on the Cairo Context
vector2 sroot = tovector2 (0,0);
vector2 diff;

//Infile Function Declarations
void init_main_window_signals();


//area signals
bool on_motion_event (GdkEventMotion* event);
bool on_expose_event (GdkEventExpose* event);
bool on_button_event (GdkEventButton* event);
bool on_focus_out_event(GdkEventFocus* event);
bool on_button_r_event (GdkEventButton* event);

//mouse scroll signals
bool on_scroll_event(GdkEventScroll* event);
void factordown ();
void factorup ();


//scroll signals
void adjust_scrolls();
bool change_hslider(Gtk::ScrollType scroll, double new_value);
bool change_vslider(Gtk::ScrollType scroll, double new_value);

//menu signals
void menu_rotate();
void menu_library();
void menu_about();
void menu_property();
void menu_close();
void menu_delete();

//Selected component's index
int selected_ci=-1;
bool isclicked=false;

int get_selected_index()
{
return selected_ci;
}

//#############################################################################
//Main Window Constructor
//#############################################################################
bool init_main_window(int argc, char *argv[])
{

	applog.initlog("log");

	read_settings ("settings.xml");

	applog.logstr("init_main_window ()");

	Gtk::Main kit(argc, argv);
	applog.logstr("GTK Init");


	refXml = Gnome::Glade::Xml::create(GLADE_FILE);
	applog.logstr("Get glade reference: refXml");


	refXml->get_widget("main_window", main_win);
	applog.logstr("Read main_window from gui.glade");

	init_main_window_signals();
	applog.logstr("Signals connectet");

	Gtk::DrawingArea* myArea;
	refXml->get_widget("drawingarea1",myArea);
	applog.logstr("Read drawingarea: drawingarea1");


	myContext = myArea->get_window()->create_cairo_context();
	applog.logstr("Create cairo context: myContext");

	myContext->set_line_cap(Cairo::LineCap(1));
	myContext->set_line_join(Cairo::LineJoin(1));


	prj.init(myContext);
	applog.logstr("Init Project");

	if (main_win)
	{
		applog.logstr("Show main_window");
		kit.run(*main_win);
	}

	return true;
}
//#############################################################################
//End of Main Window Constructor
//#############################################################################




//#############################################################################
//Helper Functions
//#############################################################################
//set the active component string // will be called from library.cc
void set_part_name(std::string cname)
{ part=cname; }
//log(str) function. this is an important function.
void log(std::string message)
{ applog.logstr(message); }
//#############################################################################
//End of Helper Functions
//#############################################################################










//#############################################################################
//Signal Binding
//#############################################################################
//binds the signals of the glade file to the c++
void init_main_window_signals()
{
	Gtk::DrawingArea* darea;
	refXml->get_widget("drawingarea1", darea);
	darea->signal_motion_notify_event().connect(sigc::ptr_fun(on_motion_event));
	darea->signal_button_press_event().connect(sigc::ptr_fun(on_button_event));
	darea->signal_button_release_event().connect(sigc::ptr_fun(on_button_r_event));
	darea->signal_expose_event().connect(sigc::ptr_fun(on_expose_event));
	darea->signal_scroll_event().connect(sigc::ptr_fun(on_scroll_event));
	darea->signal_focus_out_event().connect(sigc::ptr_fun(on_focus_out_event));
	applog.logstr("drawingarea1 signals connected");


	Gtk::MenuItem* menu;
	refXml->get_widget("main_window_menu_rotate",menu);
	menu->signal_activate().connect(sigc::ptr_fun(menu_rotate));
	refXml->get_widget("main_window_menu_component_list",menu);
	menu->signal_activate().connect(sigc::ptr_fun(menu_library));
	refXml->get_widget("main_window_menu_about",menu);
	menu->signal_activate().connect(sigc::ptr_fun(menu_about));
	refXml->get_widget("main_window_menu_active_component_property",menu);
	menu->signal_activate().connect(sigc::ptr_fun(menu_property));
	refXml->get_widget("main_window_menu_close",menu);
	menu->signal_activate().connect(sigc::ptr_fun(menu_close));
	refXml->get_widget("main_window_menu_delete",menu);
	menu->signal_activate().connect(sigc::ptr_fun(menu_delete));

	/*
	Gtk::Entry* entry;
	refXml->get_widget("main_window_command",entry);
	entry->signal_event().connect(sigc::ptr_fun(on_commandbutton_key_press));
	*/

	Gtk::HScrollbar* gscale;
	Gtk::VScrollbar* gscale2;
	refXml->get_widget("hscrollbar1",gscale);
	gscale->signal_change_value().connect(sigc::ptr_fun(change_hslider));
	refXml->get_widget("vscrollbar1",gscale2);
	gscale2->signal_change_value().connect(sigc::ptr_fun(change_vslider));

	log("Signals are connected");
}
//#############################################################################
//End of Signal Binding
//#############################################################################



//#############################################################################
//Scroll Signals
//#############################################################################
bool change_vslider(Gtk::ScrollType scroll, double new_value)
{
	Gtk::VScrollbar* gscale;
	refXml->get_widget("vscrollbar1",gscale);
	sroot.y =  gscale->get_value();
	prj.active_sheet->mysheet.setroot(sroot);
	prj.print_components();

}
//#############################################################################
bool change_hslider(Gtk::ScrollType scroll, double new_value)
{
	Gtk::HScrollbar* gscale;
	refXml->get_widget("hscrollbar1",gscale);
	sroot.x = gscale->get_value();
	prj.active_sheet->mysheet.setroot(sroot);
	prj.print_components();
}
//#############################################################################
void adjust_scrolls()
{

	Gtk::Adjustment* adj;
	Gtk::VScrollbar* gscale;
	refXml->get_widget("vscrollbar1",gscale);
	adj = gscale->get_adjustment();
	adj->set_upper(2000*prj.active_sheet->mysheet.getfactor());
	gscale->set_adjustment(*adj);
	Gtk::HScrollbar* gscale2;
	refXml->get_widget("hscrollbar1",gscale2);
	adj = gscale2->get_adjustment();
	adj->set_upper(2000*prj.active_sheet->mysheet.getfactor());
	gscale2->set_adjustment(*adj);

}
//#############################################################################
//End of Scroll Signals
//#############################################################################








//#############################################################################
//Area Signals
//#############################################################################
//the click signal of the drawing area
bool on_button_r_event (GdkEventButton* event)
{
	if(event->type == GDK_BUTTON_RELEASE)
		isclicked=false;
}
bool on_button_event (GdkEventButton* event)
{


	if(event->type == GDK_BUTTON_PRESS && event->button == 1)
	{
		if(part=="")
		{
			selected_ci = prj.isonwho(pos);
			if(selected_ci!=-1)
			{
				diff.x =sroot.x + pos.x - prj.get_component(selected_ci).position.x;
				diff.y =sroot.y + pos.y - prj.get_component(selected_ci).position.y;
				isclicked=true;
			}
		}
		else
		{
			prj.add_component(part,pos);
			prj.print_components();
		}
	}
	else if(event->type == GDK_BUTTON_PRESS && event->button == 3)
	{
		part="";
		prj.print_components();
	}
}
//#############################################################################
bool on_expose_event (GdkEventExpose* event)
{
	prj.print_components();
}
bool on_focus_out_event(GdkEventFocus* event)
{
	//prj.print_components();
}
//#############################################################################
bool on_scroll_event(GdkEventScroll* event)
{
	if(event->direction == GDK_SCROLL_UP)
		factorup();
	else if (event->direction == GDK_SCROLL_DOWN)
		factordown();
}
//#############################################################################
void factordown ()
{
	prj.active_sheet->mysheet.setfactor(prj.active_sheet->mysheet.getfactor()-0.5);

	prj.active_sheet->mysheet.changed=true;

	prj.print_components();

	adjust_scrolls();

}
//#############################################################################
void factorup ()
{
	prj.active_sheet->mysheet.setfactor(prj.active_sheet->mysheet.getfactor()+0.5);

	prj.active_sheet->mysheet.changed=true;

	prj.print_components();

	adjust_scrolls();
}
//#############################################################################
//Gets the position of the mouse and saves it on a vector (pos)
bool on_motion_event (GdkEventMotion* event)
{

	pos.x = togridvalue ((float)event->x, prj.active_sheet->mysheet.getfactor());
	pos.y = togridvalue((float)event->y, prj.active_sheet->mysheet.getfactor());



	if(isgridchage (pos)==true)
		prj.active_sheet->mysheet.changed=true;
	else
		prj.active_sheet->mysheet.changed=false;

	if(part!="")
		prj.tadd_component(myContext, part,pos);
	else
		if(selected_ci!=-1 && isclicked==true)
		{

			prj.get_component(selected_ci).position=tovector2 (-diff.x+sroot.x+pos.x,-diff.y+sroot.y+pos.y);
			prj.isonwho(pos);
		}


}
//#############################################################################
//End of Area Signals
//#############################################################################








//#############################################################################
//Menu Signals
//#############################################################################
void menu_delete()
{
	prj.active_sheet->mysheet.add_wire(tovector2 (0,0),tovector2 (40,40),3);
	prj.active_sheet->mysheet.add_wire(tovector2 (50,50),tovector2 (80,50),3);
	prj.active_sheet->mysheet.add_wire(tovector2 (80,50),tovector2 (80,100),3);
	prj.print_components();
}
void menu_close()
{
	main_win->hide();
}
//#############################################################################
void menu_library()
{
	show_library_window (refXml);
}
//#############################################################################
void menu_property()
{
	show_property_window (refXml,prj);
}
//#############################################################################
void menu_about()
{
    show_about_window(refXml);
}
//#############################################################################
void menu_rotate()
{
	if(selected_ci>=0)
		if(prj.get_component(selected_ci).get_angle()==1)
		{
			prj.get_component(selected_ci).set_angle(0);
			prj.print_components();
			prj.isonwho(pos);
		}
		else if(prj.get_component(selected_ci).get_angle()==0)
		{
			prj.get_component(selected_ci).set_angle(1);
			prj.print_components();
			prj.isonwho(pos);
		}
}
//#############################################################################
//End of Menu Signals
//#############################################################################
